﻿//#include "pch.h"
#include "MaterialSynchronize.h"
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <sqlite3.h>
#include <nlohmann/json.hpp>
#include <curl/curl.h>
#include <iomanip>

using json = nlohmann::json;

// 结构体：表示配置文件中字段到数据库中的映射关系
struct FieldMapping {
    std::string source_path;   // JSON中的嵌套路径，如"EngineeringProperty.MaterialForm"
    std::string target_column; // 数据库表中的列名
    std::string sqlite_type;   // SQLite数据类型，如"TEXT", "REAL", "INTEGER"
};

// 用于接收 HTTP 响应的回调函数
static size_t WriteCallback(void* contents, size_t size, size_t nmemb, std::string* userp) {
    userp->append((char*)contents, size * nmemb);
    return size * nmemb;
}

// 解析配置文件中的字段映射定义
static std::vector<FieldMapping> parseConfig(const std::string& config_path) {
    std::ifstream config_file(config_path);
    json config_json;
    config_file >> config_json;

    std::vector<FieldMapping> mappings;
    for (const auto& item : config_json["mappings"]) {
        FieldMapping fm;
        fm.source_path = item["source"];
        fm.target_column = item["target"];
        fm.sqlite_type = item["type"];
        mappings.push_back(fm);
    }
    return mappings;
}

// 根据路径从给定JSON对象中获取值
static json getJsonValue(const json& obj, const std::string& path) {
    std::vector<std::string> parts;
    size_t start = 0, end = 0;
    while ((end = path.find('.', start)) != std::string::npos) {
        parts.push_back(path.substr(start, end - start));
        start = end + 1;
    }
    parts.push_back(path.substr(start));

    json current = obj;
    for (const auto& part : parts) {
        if (current.is_null() || !current.contains(part)) {
            return nullptr;
        }
        current = current[part];
    }
    return current;
}

// 创建数据库表格
static void createTable(sqlite3* db, const std::vector<FieldMapping>& mappings, const std::string& table_name) {
    std::string create_sql = "CREATE TABLE IF NOT EXISTS " + table_name + " (";
    for (size_t i = 0; i < mappings.size(); ++i) {
        create_sql += mappings[i].target_column + " " + mappings[i].sqlite_type;
        if (i < mappings.size() - 1) create_sql += ",";
    }
    create_sql += ")";

    char* err_msg;
    if (sqlite3_exec(db, create_sql.c_str(), nullptr, nullptr, &err_msg) != SQLITE_OK) {
        std::cerr << "创建表失败: " << err_msg << std::endl;
        sqlite3_free(err_msg);
    }
}

// 插入单条数据到数据库
static void insertData(sqlite3* db, const std::vector<FieldMapping>& mappings, const std::string& table_name, const json& data_row) {
    std::string insert_sql = "INSERT INTO " + table_name + " (";
    std::string values_part = " VALUES (";

    for (size_t i = 0; i < mappings.size(); ++i) {
        insert_sql += mappings[i].target_column;
        values_part += "?";
        if (i < mappings.size() - 1) {
            insert_sql += ",";
            values_part += ",";
        }
    }
    insert_sql += ")" + values_part + ")";

    sqlite3_stmt* stmt;
    if (sqlite3_prepare_v2(db, insert_sql.c_str(), -1, &stmt, nullptr) != SQLITE_OK) {
        std::cerr << "预处理失败: " << sqlite3_errmsg(db) << std::endl;
        return;
    }

    for (int i = 0; i < mappings.size(); ++i) {
        auto value = getJsonValue(data_row, mappings[i].source_path);
        if (value.is_null()) {
            sqlite3_bind_null(stmt, i + 1);
        }
        else {
            if (mappings[i].sqlite_type == "TEXT") {
                sqlite3_bind_text(stmt, i + 1, value.get<std::string>().c_str(), -1, SQLITE_TRANSIENT);
            }
            else if (mappings[i].sqlite_type == "REAL") {
                sqlite3_bind_double(stmt, i + 1, value.get<double>());
            }
            else if (mappings[i].sqlite_type == "INTEGER") {
                sqlite3_bind_int(stmt, i + 1, value.get<int>());
            }
        }
    }

    if (sqlite3_step(stmt) != SQLITE_DONE) {
        std::cerr << "插入失败: " << sqlite3_errmsg(db) << std::endl;
    }
    sqlite3_finalize(stmt);
}

// 获取认证 token
static std::string get_token(const std::string& auth_url, const std::string& tenant_id,
    const std::string& username, const std::string& password,
    bool remember_me, const std::string& client_id,
    const std::string& grant_type) {
    CURL* curl = curl_easy_init();
    std::string token;

    if (curl) {
        std::string readBuffer;

        // 构建 JSON 请求体
        json payload = {
            {"tenantId", tenant_id},
            {"username", username},
            {"password", password},
            {"rememberMe", remember_me},
            {"clientId", client_id},
            {"grantType", grant_type}
        };
        std::string payload_str = payload.dump();

        // 设置请求头
        struct curl_slist* headers = nullptr;
        headers = curl_slist_append(headers, "Content-Type: application/json");
        headers = curl_slist_append(headers, "User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36");

        curl_easy_setopt(curl, CURLOPT_URL, auth_url.c_str());
        curl_easy_setopt(curl, CURLOPT_POSTFIELDS, payload_str.c_str());
        curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);

        CURLcode res = curl_easy_perform(curl);
        if (res == CURLE_OK) {
            try {
                json response = json::parse(readBuffer);
                if (response.contains("data") && response["data"].contains("access_token") && !response["data"]["access_token"].is_null()) {
                    token = response["data"]["access_token"];
                    std::cout << "成功获取token" << std::endl;
                }
                else {
                    std::cerr << "错误：服务器返回的token为空或格式不正确" << std::endl;
                }
            }
            catch (const json::exception& e) {
                std::cerr << "JSON解析错误: " << e.what() << std::endl;
            }
        }
        else {
            std::cerr << "请求失败: " << curl_easy_strerror(res) << std::endl;
        }

        curl_slist_free_all(headers);
        curl_easy_cleanup(curl);
    }
    return token;
}

// 下载数据
static bool download_data(const std::string& url, const std::string& token,
    const std::string& client_id, const std::string& output_file) {
    CURL* curl = curl_easy_init();
    bool success = false;

    if (curl) {
        std::string readBuffer;

        // 构建请求头
        struct curl_slist* headers = nullptr;
        headers = curl_slist_append(headers, ("Authorization: Bearer " + token).c_str());
        headers = curl_slist_append(headers, "Content-Type: application/json");
        headers = curl_slist_append(headers, ("clientId: " + client_id).c_str());

        // 构建请求体
        //不用了，用不到了，GET方法不用写请求体
        // json data = {
        //     {"conditons", json::array()},
        //     {"pageQuery", {
        //         {"pageNum", 1},
        //         {"pageSize", 100},
        //         {"orderByColumn", "_id"},
        //         {"isAsc", "desending"}
        //     }}
        // };
        // std::string data_str = data.dump();

        curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
        //curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data_str.c_str());
        curl_easy_setopt(curl, CURLOPT_HTTPGET, 1L);  // 设置为 GET 请求
        curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback);
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer);

        CURLcode res = curl_easy_perform(curl);
        if (res == CURLE_OK) {
            try {
                json response = json::parse(readBuffer);
                std::ofstream out(output_file);
                out << std::setw(4) << response;
                std::cout << "数据下载成功并保存到 " << output_file << std::endl;
                success = true;
            }
            catch (const json::exception& e) {
                std::cerr << "数据JSON解析错误: " << e.what() << std::endl;
            }
        }
        else {
            std::cerr << "请求失败: " << curl_easy_strerror(res) << std::endl;
        }

        curl_slist_free_all(headers);
        curl_easy_cleanup(curl);
    }
    return success;
}

// 读取主配置文件
static json readMainConfig(const std::string& config_path = "config.json") {
    try {
        std::ifstream config_file(config_path);
        if (!config_file.is_open()) {
            std::cerr << "无法打开配置文件: " << config_path << std::endl;
            return json();
        }

        json config;
        config_file >> config;
        return config;
    }
    catch (const json::exception& e) {
        std::cerr << "配置文件解析错误: " << e.what() << std::endl;
        return json();
    }
}

// 同步函数实现 - 无参数版本
extern "C" bool synchronize() {
    // 读取主配置文件
    json config = readMainConfig();
    if (config.empty()) {
        return false;
    }

    // 提取配置参数
    std::string auth_url = config["auth"]["url"];
    std::string tenant_id = config["auth"]["tenant_id"];
    std::string username = config["auth"]["username"];
    std::string password = config["auth"]["password"];
    bool remember_me = config["auth"]["remember_me"];
    std::string client_id = config["auth"]["client_id"];
    std::string grant_type = config["auth"]["grant_type"];

    std::string data_url = config["data"]["url"];
    std::string temp_file = config["data"]["temp_file"];

    std::string db_name = config["database"]["name"];
    std::string table_name = config["database"]["table"];

    std::string mapping_config = config["mapping"]["config_path"];

    // 初始化 curl
    curl_global_init(CURL_GLOBAL_DEFAULT);

    // 获取 token
    std::string token = get_token(auth_url, tenant_id, username, password, remember_me, client_id, grant_type);
    if (token.empty()) {
        std::cerr << "获取token失败，无法继续下载数据" << std::endl;
        curl_global_cleanup();
        return false;
    }

    // 下载数据
    if (!download_data(data_url, token, client_id, temp_file)) {
        curl_global_cleanup();
        return false;
    }

    // 解析字段映射配置
    auto mappings = parseConfig(mapping_config);

    // 读取输入JSON数据
    std::ifstream json_file(temp_file);
    json json_data;
    try {
        json_file >> json_data;
    }
    catch (const json::exception& e) {
        std::cerr << "JSON文件解析错误: " << e.what() << std::endl;
        curl_global_cleanup();
        return false;
    }

    // 连接SQLite数据库
    sqlite3* db;
    if (sqlite3_open(db_name.c_str(), &db) != SQLITE_OK) {
        std::cerr << "数据库打开失败: " << sqlite3_errmsg(db) << std::endl;
        curl_global_cleanup();
        return false;
    }

    // 创建数据库表格
    createTable(db, mappings, table_name);

    // 插入数据，遍历所有数据项目
    if (json_data.contains("data") && json_data["data"].is_array()) {
        const json& data_array = json_data["data"];
        for (const auto& item : data_array) {
            insertData(db, mappings, table_name, item);
        }
        std::cout << "数据导入完成！" << std::endl;
    }
    else {
        std::cerr << "JSON数据格式不正确，缺少data数组" << std::endl;
        sqlite3_close(db);
        curl_global_cleanup();
        return false;
    }

    // 关闭数据库连接
    sqlite3_close(db);

    // 清理 curl
    curl_global_cleanup();

    return true;
}